﻿using FinalPointSet.Model.Util;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace FinalPointSet.Model.Model.MockData
{
    public class MockParser
    {
        /// <summary>
        /// 解析字段
        /// </summary>
        /// <param name="mockFields">字段</param>
        /// <param name="mockScripts">脚本</param>
        /// <param name="mockCnt">生成的数量</param>
        /// <returns></returns>
        public static MockResult Parse(List<MockField> mockFields, List<MockRule> mockScripts, int mockCnt)
        {
            List<List<string>> fieldDatas = [];
            //循环每个字段
            foreach (var mockField in mockFields)
            {
                MockRule mockScript = mockScripts.First(e => e.ID == mockField.MockTypeID);
                Dictionary<string, string> extraInput = new()
                {
                    { "startIndex", "1" },
                    { "endIndex",  mockCnt.ToString()},
                    { "fieldName", mockField.FieldName},
                };
                string jsonArg = RunnableScriptHelper.SerSerializeInput(mockField.Param, extraInput);
                string result = RunnableScriptHelper.GenerateWithLog(mockScript, jsonArg);
                string[] results = result.Split('#');
                fieldDatas.Add([.. results]);
            }

            MockResult mockResult = new()
            {
                //提取表头,即每个字段的名称
                Header = mockFields.Select(n => n.FieldName).ToList(),
                FieldDatas = MethodUtil.Transpose(fieldDatas),
            };

            return mockResult;
        }

        public static async Task<MockResult?> Parse(List<MockField> mockFields, List<MockRule> mockScripts, int mockCnt, IProgress<int> progress, CancellationToken cancellationToken)
        {
            List<List<string>> fieldDatas = [];
            await Task.Run(() =>
            {
                //循环每个字段
                for (int i = 0; i < mockFields.Count; i++)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        fieldDatas = [];
                        return;
                    }

                    MockRule mockScript = mockScripts.First(e => e.ID == mockFields[i].MockTypeID);
                    Dictionary<string, string> extraInput = new()
                    {
                        { "startIndex", "1" },
                        { "endIndex",  mockCnt.ToString()},
                        { "fieldName", mockFields[i].FieldName},
                    };
                    string jsonArg = RunnableScriptHelper.SerSerializeInput(mockFields[i].Param, extraInput);
                    string result = RunnableScriptHelper.GenerateWithLog(mockScript, jsonArg);
                    string[] results = result.Split('#');
                    fieldDatas.Add([.. results]);
                    // 报告进度  
                    int currentProgress = ((i + 1) * 100 / mockFields.Count);
                    progress?.Report(currentProgress);
                }
            }, cancellationToken);

            if (fieldDatas.Count == 0)
            {
                return null;
            }
            else
            {
                MockResult mockResult = new()
                {
                    //提取表头,即每个字段的名称
                    Header = mockFields.Select(n => n.FieldName).ToList(),
                    FieldDatas = MethodUtil.Transpose(fieldDatas),
                };
                return mockResult;
            }
        }
        /// <summary>
        /// 根据映射规则, 识别出字段应该匹配的脚本
        /// </summary>
        /// <param name="mockFields"></param>
        /// <param name="mockScripts"></param>
        /// <param name="mockFieldClassifies"></param>
        /// <param name="mockFieldMappingRule"></param>
        /// <returns></returns>
        public static void IdentifyFieldMatchScript(
            List<MockField> mockFields,
            List<MockRule> mockScripts,
            List<MockFieldClassify> mockFieldClassifies,
            List<MockFieldMappingRule> mockFieldMappingRule)
        {
            ClassfiyType[] fieldClassifies = new ClassfiyType[mockFields.Count];
            for (int i = 0; i < mockFields.Count; i++)
            {
                string fieldName = mockFields[i].FieldName;
                string fieldType = mockFields[i].FieldType;
                fieldClassifies[i] = ClassfiyType.String;
                //识别字段的划分大的类型
                foreach (MockFieldClassify classify in mockFieldClassifies)
                {
                    //判断字段类型是否一致
                    if (classify.FieldTypes.Contains(fieldType, System.StringComparison.OrdinalIgnoreCase))
                    {
                        fieldClassifies[i] = classify.ClassfiyType;
                        break;
                    }
                }

                //识别字段具体使用哪个脚本生成数据
                foreach (MockFieldMappingRule rule in mockFieldMappingRule)
                {
                    bool isMatch = false;
                    MockRule customScript = mockScripts.FirstOrDefault(ms => ms.ID == rule.RuleID, new());
                    if (rule.MappingMatchType == MappingMatchType.ClassfiyType)
                    {
                        //判断字段类型是否一致
                        if (rule.ClassfiyType == fieldClassifies[i])
                        {
                            isMatch = true;
                        }
                    }
                    else if (rule.MappingMatchType == MappingMatchType.Keyword)
                    {
                        //判断字段类型是否一致 && 字段名称是否包含关键词
                        if (rule.ClassfiyType == fieldClassifies[i] && IsContainKeywordInArrayString(fieldName, rule.Keyword))
                        {
                            isMatch = true;
                        }
                    }

                    //匹配上, 则初始化字段值
                    if (isMatch)
                    {
                        mockFields[i].MockTypeID = rule.RuleID;
                        mockFields[i].Script = customScript;
                        List<MockParamTemplate> mpts = [.. customScript.ParamTemplates.Reverse()];
                        //检测参数模板有无匹配
                        foreach (MockParamTemplate mpt in mpts)
                        {
                            if (string.IsNullOrEmpty(mpt.Keyword) || IsContainKeywordInArrayString(fieldName, mpt.Keyword))
                            {
                                mockFields[i].ParamTemplate = mpt;
                                break;
                            }
                        }

                        mockFields[i].Param = mockFields[i].ParamTemplate.Value;
                    }
                }
            }
        }

        /// <summary>
        /// 判断字段名称中, 是否包含多个关键词(以逗号隔开的字符串)
        /// </summary>
        /// <param name="fieldName">字段名称</param>
        /// <param name="keywordArrayString">关键词(以逗号隔开的字符串)</param>
        /// <returns></returns>
        private static bool IsContainKeywordInArrayString(string fieldName, string keywordArrayString)
        {
            string[] keywords = keywordArrayString.Split(",");
            foreach (string keyword in keywords)
            {
                if (fieldName.Contains(keyword.ToString(), System.StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
            }
            return false;
        }
    }
}
